// 粒子效果 工具
(function(){
	//配置
	/*
	var config = {
		containerId: "mydiv",// canvas标签放入的标签id
		vx: 4,	//小球x轴速度,正为右，负为左
		vy: 4,	//小球y轴速度
		height: 2,	// 和width保持一致
		width: 2, // 小球半径
		count: 100,		//点个数
		color: "rgb(211, 0, 255)", 	//点颜色
		stroke: "rgb(121, 0, 147)", 		//线条颜色
		dist: 6000, 	//点吸附距离
		m_dist: 16000, 	//鼠标吸附加速距离
		max_conn: 10, 	//点到点最大连接数
		othersStyle: "background: linear-gradient(to left top, #ff3e3e 0%, #1919ff 100%);"  // 背景
	}
	//调用
	let cp = canvasParticle(config);
	*/
	var CanvasParticle = function(config){
		var myConfig = config || {};
		this.canvasObj = document.createElement("canvas");
		this.containerObj = null;
		this.points = [];
		this.config = {
			time: myConfig.time || 50,
			vx: myConfig.vx || 4,
			vy: myConfig.vy || 4,
			height: myConfig.height || 3,
			width: myConfig.width || 3,
			count: myConfig.count || 100,
			color: myConfig.color || "rgb(0, 255, 237)",
			stroke: myConfig.stroke || "0, 255, 147",
			dist: myConfig.dist || 10000,
			m_dist: myConfig.m_dist || 18000,
			max_conn: myConfig.max_conn || 10,
			othersStyle: myConfig.othersStyle || "background: linear-gradient(to left top, #ff3e3e 0%, #1919ff 100%);"
		};

		this.base_size = 50;
		this.center = { x: this.canvasObj.width/2, y: this.canvasObj.height/2};

		// 初始化
		this.init = function (){
			this.ctx = this.canvasObj.getContext("2d");// 笔触
			this.canvasObj.style = "position: fixed;top: 0;left: 0;z-index: -1;"
			+ this.config.othersStyle;

			this.containerObj = this.myGetOne('body');
			if(myConfig.containerId){
				this.containerObj = this.myGetOne('#' + myConfig.containerId);
			}
			this.containerObj.appendChild(this.canvasObj);

			this.canvasReset();
			this.initPoints();
			var _this = this;

			this.center.x = this.canvasObj.width / 2;
			this.center.y = this.canvasObj.height / 2;
			// 中心位置
			// console.log(this.center);

			window.onresize = function() {
				_this.canvasReset();
				// _this.initPoints();
			};
			var body = this.myGetOne('body');
			
			body.onmousemove = function(e) {
				var event = e || window.event;
				let x = Math.floor(event.clientX);
				let y = Math.floor(event.clientY);
				
				_this.mouse = { x: x, y: y };

				// _this.drawPoints();
			};
			body.onmouseover = function(e) {
				var event = e || window.event;
				let x = Math.floor(event.clientX);
				let y = Math.floor(event.clientY);
				let mouse = { x: x, y: y };
				// console.log('onmouseover', mouse);
			};
			body.onmouseleave = function() {
				_this.mouse = undefined;
			};
			this.timer = setInterval(function(){
				_this.drawPoints();
			}, this.config.time);
		};
		// 重置 宽高
		this.canvasReset = function () {
			var containerObj = this.containerObj;
			// 根据容器调整 canvas
			var width = containerObj.style.width;
			var height = containerObj.style.height;
			width = width || document.documentElement.clientWidth;
			height = height || document.documentElement.clientHeight;
			this.canvasObj.width = width;
			this.canvasObj.height = height;
		};
		// 初始化 点
		this.initPoints = function (){
			var pointArr = [];
			for(var i=0;i<this.config.count;i++){
				var p = {
					x: Math.floor(Math.random() * this.canvasObj.width),
					y: Math.floor(Math.random() * this.canvasObj.height),
					vx: this.config.vx / 2 - Math.random() * this.config.vx,
					vy: this.config.vy / 2 - Math.random() * this.config.vy,
					max_conn: 0,
					r: this.config.width,
					size: this.config.width
				};
				if(p.vx < 0 && p.vx > -1){
					p.vx = -1;
				}
				if(p.vy < 0 && p.vy > -1){
					p.vy = -1;
				}
				if(p.vx > 0 && p.vx < 1){
					p.vx = 1;
				}
				if(p.vy > 0 && p.vy < 1){
					p.vy = 1;
				}
				pointArr.push(p);
			}
			this.points = pointArr;
		};
		// 绘图
		this.drawPoints = function (){
			var pArr = this.points;
			var ctx = this.ctx;
			var width = this.config.width;
			var height = this.config.height;
			// 清空画板
			ctx.clearRect(0, 0, this.canvasObj.width, this.canvasObj.height);
			ctx.save();
			this.doChange();

			// 给绘制的 点 设置填充颜色
			ctx.fillStyle = this.config.color;
			for(var i=0;i<pArr.length;i++){
				var point = pArr[i];
				// 让点移动, 需要重置 位置等属性
				this.setMyPoint(point);
				
				// 绘制 点
				ctx.beginPath();
				ctx.arc(point.x, point.y, point.size, 0, 2*Math.PI, true);

				ctx.closePath();

				ctx.fill();
			}
			this.drawLine();

			ctx.restore();
		};
		this.ox;
		this.oy;
		this.doChange = function () {
			if(this.mouse){
				let _this = this;
				let center = this.center;
				let mouse = this.mouse;

				let offsetX = Math.floor(center.x - mouse.x);
				let offsetY = Math.floor(center.y - mouse.y);
				let ctx = this.ctx;
				
				// console.log(offsetX, offsetY);

				this.ox = Math.ceil(offsetX/center.x * this.base_size);
				this.oy = Math.ceil(offsetY/center.y * this.base_size);

				ctx.translate(this.ox, this.oy);
			}
		};
		// 设置 点的 属性 
		this.setMyPoint = function (point) {
			var p = point;
			var width = this.canvasObj.width;
			var height = this.canvasObj.height;
			// 简单边界判断
			if (p.x <= 0 || p.x >= width) {
				p.vx = -1 * p.vx;
				p.x = p.x + p.vx;
			} else if (p.y <= 0 || p.y >= height) {
				p.vy = -1 * p.vy;
				p.y = p.y + p.vy;
			} else {
				p.x = p.x + p.vx;
				p.y = p.y + p.vy;
			}
			return p;
		};
		// 绘制线
		this.drawLine = function () {
			var width = this.config.width;
			var height = this.config.height;
			var ctx = this.ctx;
			var pArr = this.points;
			var config_dist = this.config.dist;
			var config_max_conn = this.config.max_conn;
			for(var i=0;i<pArr.length;i++){
				var p1 = pArr[i];
				p1.max_conn = 0;
				for(var j=0;j<pArr.length;j++){
					if(i != j){// 不是自己
						var p2 = pArr[j];
						var dist = this.getDist(p1, p2);
						// 在指定的 长度,数量 内画线
						if(dist <= config_dist && p1.max_conn < config_max_conn){
							p1.max_conn++;
							// 设置线宽, 越近线越宽
							var lw = 1 - dist / config_dist;
							ctx.lineWidth = lw;
							// 设置 线 颜色
							ctx.strokeStyle = "rgba("+this.config.stroke+","+lw+")";
							// TODO: 偏移
							// ctx.rotate(Math.PI*2/360 * 10);
							// 开始
							ctx.beginPath();
							ctx.moveTo(p1.x, p1.y);
							ctx.lineTo(p2.x, p2.y);
							// 结束
							ctx.stroke();
						}
					}
				}

				if(this.mouse){// 鼠标出现
					var mouse = {
						x: this.mouse.x - this.ox,
						y: this.mouse.y - this.oy
					};
					var dist = this.getDist(p1, mouse);// 两者间距离

					// 在牵引距离内时，执行加速牵引
					if(dist > config_dist && dist <= this.config.m_dist) {
						p1.x = p1.x + (mouse.x - p1.x) / 20;
						p1.y = p1.y + (mouse.y - p1.y) / 20;
					}
					// 达到可连线距离时，连线
					if(dist <= this.config.m_dist) {
						// 设置固定线宽
						var lw = 1 - dist / this.config.m_dist;
						ctx.lineWidth = 1;//线宽
						ctx.strokeStyle = "rgba("+this.config.stroke+","+lw+")";// 线的样式
						// 开始
						ctx.beginPath();
						ctx.moveTo(p1.x, p1.y);
						ctx.lineTo(mouse.x, mouse.y);
						// 结束
						ctx.stroke();
					}
				}
			}
		};
		// 工具函数
		this.myGetAll = function (selector){
			var arr = document.querySelectorAll(selector);
			return arr;
		};
		// 工具函数
		this.myGetOne = function myGetOne(selector){
			var arr = document.querySelectorAll(selector);
			return arr.length == 0 ? null : arr[0];
		};
		// 两点之间距离
		this.getDist = function(p1, p2){
			var z = Math.pow((p1.x - p2.x), 2) + Math.pow((p1.y - p2.y), 2);// 结果 z*z
			return z;
		}
		// 停止
		this.stop = function(){
			clearInterval(this.timer);
		};
		// 停止后的 再启动
		this.start = function(){
			this.stop();
			var _this = this;
			this.timer = setInterval(function(){
				_this.drawPoints();
			}, this.config.time);
		};
	};

	window.canvasParticle = function (config) {
		var cp = new CanvasParticle(config);
		cp.init();
		return cp;
	};
})();